package org.ly2048.com.ly2048.activity;

import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.TextView;

import org.ly2048.com.ly2048.R;
import org.ly2048.com.ly2048.utils.SPUtils;
import org.ly2048.com.ly2048.view.Item2048;

import java.util.ArrayList;
import java.util.List;

public class Game2048Activity extends AppCompatActivity {

    private ImageView img_back;
    private GridLayout game_broad;
    private TextView title_restart,curr_max_score, curr_history_max;
    private int coum = 6;
    private int lastNum = -1;
    private int item_with;
    //    private List<Point> Points;
    List<Item2048> items_null;
    private List<Integer> nums;
    private float downX, downY;
    private Item2048 items[][];
    private int maxcurr_score;//当前最高分数
    private int maxcurr_history;//历史最高分数

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game2048);

        img_back = (ImageView) findViewById(R.id.img_back);
        curr_max_score = (TextView) findViewById(R.id.curr_max_score);
        curr_history_max = (TextView) findViewById(R.id.curr_history_max);
        title_restart = (TextView) findViewById(R.id.title_restart);
        img_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
        title_restart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                reStart();
            }
        });

        game_broad = (GridLayout) findViewById(R.id.game_broad);
        game_broad.setColumnCount(coum);
        //（屏幕宽度 - 边距*2 -（ 列数+1）*列距 ）/列数
        item_with = (getResources().getDisplayMetrics().widthPixels - 2 * 10 - (coum + 1) * 2) / coum;
//        Points = new ArrayList<>();
        items_null = new ArrayList<>();
        nums = new ArrayList<>();
        InitGame();
    }

    private void InitGame() {
        maxcurr_history = maxHisScore();
        curr_history_max.setText("历史最高：" + maxcurr_history);

        items = new Item2048[coum][coum];
        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                Item2048 item = new Item2048(Game2048Activity.this);
                items[i][j] = item;
                item.setNum(0);//数值
                item.setPoint(i, j);
                item.setSize(item_with, 2, coum);
                game_broad.addView(item);
            }
        }
        addNum(2);
    }

    /**
     * 选择空
     */
    private void CheckNUll() {
        items_null.clear();
        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                if (items[i][j].getNum() == 0) {
//                    Points.add(items[i][j].getPoint());
                    items_null.add(items[i][j]);
                }
            }
        }
    }

    /**
     * 创建num
     */
    private void creatNum() {
        int index = (int) (Math.random() * items_null.size());
        Item2048 item = items_null.get(index);
        int num = Math.random() > 0.1 ? 2 : 4;
        item.setNum(num);
        items_null.remove(index);
    }

    /**
     * 添加num
     *
     * @param count 添加数量
     */
    private void addNum(int count) {
        CheckNUll();
        for (int i = 0; i < count; i++) {
            if (items_null.size() > 0) {
                creatNum();
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                float dX = event.getX() - downX;
                float dY = event.getY() - downY;

                if (Math.abs(dX) < 50 && Math.abs(dY) < 50) {
                    return super.onTouchEvent(event);
                }

                if (canMove()) {
                    if (Move(getOrientation(dX, dY))) {
                        addNum(1);
                        curr_max_score.setText("当前最高：" + maxcurr_score);
                    }
                } else {
                    gameOver();
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    private void gameOver() {
        new AlertDialog.Builder(this).setMessage("游戏结束！").show();
    }

    private char getOrientation(float dX, float dY) {
        if (Math.abs(dX) > Math.abs(dY)) {
            if (dX > 0) {//右移
                return 'r';
            } else {//左移
                return 'l';
            }
        } else {
            if (dY > 0) {//下移
                return 'd';
            } else {//上
                return 't';
            }
        }
    }

    /**
     * 游戏是否结束，还能否移动
     *
     * @return
     */
    private boolean canMove() {

        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                int num = items[i][j].getNum();
                if (num == 0) {
                    return true;
                }
                if (i - 1 >= 0 && items[i][j].getNum() == items[i - 1][j].getNum()) {
                    return true;
                }
                if (i + 1 < coum && items[i][j].getNum() == items[i + 1][j].getNum()) {
                    return true;
                }
                if (j - 1 >= 0 && items[i][j].getNum() == items[i][j - 1].getNum()) {
                    return true;
                }
                if (j + 1 < coum && items[i][j].getNum() == items[i][j + 1].getNum()) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean Move(char orientation) {
        switch (orientation) {
            case 'l':
                return moveToLeft();
            case 'r':
                return moveToRight();
            case 't':
                return moveToTop();
            case 'd':
                return moveToDown();
            default:
                return false;
        }
    }

    private boolean moveToLeft() {
        boolean f = false;
        int zeroIndex = -1;

        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                int num = items[i][j].getNum();
                if (num != 0) {
                    if (zeroIndex != -1 && zeroIndex < j) {
                        f = true;
                    }
                    if (lastNum == -1) {
                        lastNum = num;
                    } else {
                        if (lastNum == num) {
                            f = true;
                            nums.add(num * 2);
                            lastNum = -1;
                        } else {
                            nums.add(lastNum);
                            lastNum = num;
                        }
                    }
                } else {
                    zeroIndex = j;
                }
            }
            if (lastNum != -1) {
                nums.add(lastNum);
            }
            for (int j = 0; j < coum; j++) {
                if (j < nums.size()) {
                    int num = nums.get(j);
                    if (maxcurr_score < num) {
                        maxcurr_score = num;
                        if (maxcurr_history < maxcurr_score) {
                            maxcurr_history = maxcurr_score;
                            saveScore();
                        }
                    }
                    items[i][j].setNum(num);
                } else items[i][j].setNum(0);
            }
            nums.clear();
            lastNum = -1;
            zeroIndex = -1;
        }
        return f;
    }

    private boolean moveToRight() {
        boolean f = false;
        int zeroIndex = -1;

        for (int i = 0; i < coum; i++) {
            for (int j = coum - 1; j >= 0; j--) {
                int num = items[i][j].getNum();
                if (num != 0) {
                    if (zeroIndex != -1 && zeroIndex > j) {
                        f = true;
                    }
                    if (lastNum == -1) {
                        lastNum = num;
                    } else {
                        if (lastNum == num) {
                            f = true;
                            nums.add(num * 2);
                            lastNum = -1;
                        } else {
                            nums.add(lastNum);
                            lastNum = num;
                        }
                    }
                } else {
                    zeroIndex = j;
                }
            }
            if (lastNum != -1) {
                nums.add(lastNum);
            }
            for (int j = 0; j < coum; j++) {
                if (coum - 1 - j < nums.size()) {
                    int num = nums.get(coum - 1 - j);
                    if (maxcurr_score < num) {
                        maxcurr_score = num;
                        if (maxcurr_history < maxcurr_score) {
                            maxcurr_history = maxcurr_score;
                            saveScore();
                        }
                    }
                    items[i][j].setNum(num);
                } else items[i][j].setNum(0);
            }
            nums.clear();
            lastNum = -1;
            zeroIndex = -1;
        }
        return f;
    }

    private boolean moveToTop() {
        boolean f = false;
        int zeroIndex = -1;

        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                int num = items[j][i].getNum();
                if (num != 0) {
                    if (zeroIndex != -1 && zeroIndex < j) {
                        f = true;
                    }
                    if (lastNum == -1) {
                        lastNum = num;
                    } else {
                        if (lastNum == num) {
                            f = true;
                            nums.add(num * 2);
                            lastNum = -1;
                        } else {
                            nums.add(lastNum);
                            lastNum = num;
                        }
                    }
                } else {
                    zeroIndex = j;
                }
            }
            if (lastNum != -1) {
                nums.add(lastNum);
            }
            for (int j = 0; j < coum; j++) {
                if (j < nums.size()) {
                    int num = nums.get(j);
                    if (maxcurr_score < num) {
                        maxcurr_score = num;
                        if (maxcurr_history < maxcurr_score) {
                            maxcurr_history = maxcurr_score;
                            saveScore();
                        }
                    }
                    items[j][i].setNum(num);
                } else items[j][i].setNum(0);
            }
            nums.clear();
            lastNum = -1;
            zeroIndex = -1;
        }
        return f;
    }

    private boolean moveToDown() {
        boolean f = false;
        int zeroIndex = -1;

        for (int i = 0; i < coum; i++) {
            for (int j = coum - 1; j >= 0; j--) {
                int num = items[j][i].getNum();
                if (num != 0) {
                    if (zeroIndex != -1 && zeroIndex > j) {
                        f = true;
                    }
                    if (lastNum == -1) {
                        lastNum = num;
                    } else {
                        if (lastNum == num) {
                            f = true;
                            nums.add(num * 2);
                            lastNum = -1;
                        } else {
                            nums.add(lastNum);
                            lastNum = num;
                        }
                    }
                } else {
                    zeroIndex = j;
                }
            }
            if (lastNum != -1) {
                nums.add(lastNum);
            }
            for (int j = 0; j < coum; j++) {
                if (coum - 1 - j < nums.size()) {
                    int num = nums.get(coum - 1 - j);
                    if (maxcurr_score < num) {
                        maxcurr_score = num;
                        if (maxcurr_history < maxcurr_score) {
                            maxcurr_history = maxcurr_score;
                            saveScore();
                        }
                    }
                    items[j][i].setNum(num);
                } else items[j][i].setNum(0);
            }
            nums.clear();
            lastNum = -1;
            zeroIndex = -1;
        }
        return f;
    }

    private void saveScore() {
        SPUtils.put("score", maxcurr_history);
        curr_history_max.setText("历史最高：" + maxcurr_history);
    }

    private int maxHisScore() {
        int Score = (int) SPUtils.get("score", 0);
        return Score;
    }

    /**
     * 重新开始
     */
    private void reStart(){
        for (int i = 0; i < coum; i++) {
            for (int j = 0; j < coum; j++) {
                items[i][j] .setNum(0);//数值
            }
        }
        addNum(2);
    }
}
